package sk.naive.talker.command;

import sk.naive.talker.*;
import sk.naive.talker.adapter.TagConsts;
import sk.naive.talker.props.PropertyStoreException;
import sk.naive.talker.message.Category;
import sk.naive.talker.util.Utils;
import sk.naive.talker.persistence.*;
import sk.naive.talker.callback.*;

import java.rmi.RemoteException;

/**
 *
 * @author <a href="mailto:virgo@naive.deepblue.sk">Richard "Virgo" Richter</a>
 * @version $Revision: 1.4 $ $Date: 2005/02/16 19:27:20 $
 */
public abstract class AbstractEditorHelper {
	protected AbstractCommand command;
	protected final User user;

	// TODO prerobit comm na dispatcher a vyriesit sendMessage
	public AbstractEditorHelper(User user, AbstractCommand comm) {
		this.user = user;
		this.command = comm;
	}

	public void start(PersistentObject object)
		throws RemoteException, CommandException
	{
		try {
			try {
				beginNotify();
			} catch (RemoteException e) {
				// ignore
			}
			String cId = user.setupCommandCallback(getCallback(object));
			Text t = getOriginalText(object, command.commandDispatcher.textPersistence());
			if (t != null) {
				user.send(Utils.tag(TagConsts.EDITOR, cId) + t.getContent());
			} else {
				user.send(Utils.tag(TagConsts.EDITOR, cId));
			}
		} catch (CallbackException e) {
			command.sendHelper().sendMessage(user, "command.callbackInstallationError");
		} catch (PersistenceException e) {
			throw new CommandException(e);
		} catch (PropertyStoreException e) {
			throw new CommandException(e);
		}
	}

	private CommandCallback getCallback(final PersistentObject object) {
		return new CommandCallback() {
			public Callback process(String s) throws CommandCallbackException {
				TextPersistence tp = null;
				try {
					DbTransaction.begin();
					tp = command.commandDispatcher.textPersistence();
					Text t = getOriginalText(object, tp);
					if (t != null) {
						t.setContent(s, tp);
					} else {
						t = createNewText(tp, s);
						tp.storeTextRelation(new TextRelation(object.getId(), t.getId(), textType(), null));
					}
					try {
						sendNotify();
					} catch (RemoteException e) {
						// ignore
					}
				} catch (PersistenceException e) {
					DbTransaction.setRollbackOnly(e.getMessage());
					throw new CommandCallbackException(e);
				} catch (PropertyStoreException e) {
					DbTransaction.setRollbackOnly(e.getMessage());
					throw new CommandCallbackException(e);
				} finally {
					DbTransaction.finishWithoutException();
				}
				return null;
			}

			public void cancel() {
				try {
					cancelNotify();
				} catch (RemoteException e) {
					// ignore
				}
			}
		};
	}

	private void doNotify(String userKey, String audienceKey, Category category) throws RemoteException {
		command.sendHelper().sendLocal(user, userKey, audienceKey, category);
	}

	protected void beginNotify() throws RemoteException {
		doNotify(getUserKeyBegin(), getAudienceKeyBegin(), getAudienceCategoryBegin());
	}

	protected void sendNotify() throws RemoteException {
		doNotify(getUserKeySend(), getAudienceKeySend(), getAudienceCategorySend());
	}

	protected void cancelNotify() throws RemoteException {
		doNotify(getUserKeyCancel(), getAudienceKeyCancel(), getAudienceCategoryCancel());
	}

	protected String getUserKeyBegin() {
		return "editor.begin";
	}

	protected String getAudienceKeyBegin() {
		return "editor.audienceBegin";
	}

	protected String getUserKeySend() {
		return "editor.successful";
	}

	protected String getAudienceKeySend() {
		return "editor.audienceOK";
	}

	protected String getUserKeyCancel() {
		return "editor.cancelled";
	}

	protected String getAudienceKeyCancel() {
		return "editor.audienceCancel";
	}

	protected Category getAudienceCategoryBegin() {
		return Category.EDITOR;
	}

	protected Category getAudienceCategorySend() {
		return Category.EDITOR;
	}

	protected Category getAudienceCategoryCancel() {
		return Category.EDITOR;
	}

	protected abstract Text createNewText(TextPersistence tp, String s) throws PersistenceException;

	protected abstract int textType();

	protected abstract Text getOriginalText(PersistentObject object, TextPersistence tp) throws PersistenceException, PropertyStoreException;
}
